home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / RARP.C < prev    next >
C/C++ Source or Header  |  1997-01-19  |  6KB  |  217 lines

  1. /* Reverse Address Resolution Protocol (ARP) functions. Sits between IP and
  2.  * Level 2, mapping Level 2 addresses to IP.
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "proc.h"
  7. #include "iface.h"
  8. #include "arp.h"
  9. #include "cmdparse.h"
  10. #include "pktdrvr.h"
  11.  
  12. #if !defined(_lint)
  13. static char rcsid[] OPTIONAL = "$Id: rarp.c,v 1.20 1997/01/19 21:13:05 root Exp root $";
  14. #endif
  15.  
  16. static struct arp_stat Rarp_stat = {0, 0, 0, 0, 0, 0, 0};
  17. static int Rwaiting = 0;    /* Semaphore used when waiting for a reply */
  18.  
  19. static int dorarpquery (int argc, char *argv[], void *p);
  20. static void rarpstat (void);
  21. static void rarp_output (struct iface * iface, int16 hardware, char *hwaddr, char *target);
  22. int dorarp (int argc, char **argv, void *p);
  23.  
  24.  
  25. static struct cmds Rarpcmds[] =
  26. {
  27.     { "query",    dorarpquery,    0, 3,
  28. #ifdef fixed
  29.         "rarp query <interface> <ether addr|callsign> [<ether addr|callsign>]",
  30. #else
  31.         "rarp query <interface> <callsign> [<callsign>]"},
  32. #endif
  33.     { NULLCHAR,    NULL,        0, 0, NULLCHAR}
  34. };
  35.  
  36.  
  37. int
  38. dorarp (int argc, char **argv, void *p)
  39. {
  40.     if (argc < 2) {
  41.         rarpstat ();
  42.         return 0;
  43.     }
  44.     return subcmd (Rarpcmds, argc, argv, p);
  45. }
  46.  
  47.  
  48. static int
  49. dorarpquery (int argc, char *argv[], void *p OPTIONAL)
  50. {
  51. struct iface *ifp;
  52. char hwaddr[MAXHWALEN], qhwaddr[MAXHWALEN];
  53. int16 hardware, t;
  54. static const char *errmsg = "Illegal hardware address\n";
  55.  
  56.     if ((ifp = if_lookup (argv[1])) == NULLIF) {
  57.         tprintf (Badinterface, argv[1]);
  58.         return -1;
  59.     }
  60.     switch (ifp->iftype->type) {
  61.         case CL_AX25:
  62.             hardware = ARP_AX25;
  63.             break;
  64. #ifdef fixed
  65.         case CL_ETHERNET:
  66.             hardware = ARP_ETHER;
  67.             break;
  68.         default:
  69.             tputs ("Only Ethernet and AX25 interfaces allowed\n");
  70. #else
  71.         default:
  72.             tputs ("Only AX25 interfaces allowed\n");
  73. #endif
  74.             return -1;
  75.     }
  76.     if ((*ifp->iftype->scan) (hwaddr, argv[2]) == -1) {
  77.         tputs (errmsg);
  78.         return -1;
  79.     }
  80.     if (argc > 3 && (*ifp->iftype->scan) (qhwaddr, argv[3]) == -1) {
  81.         tputs (errmsg);
  82.         return -1;
  83.     }
  84.     if (argc == 3)
  85.         memcpy (qhwaddr, hwaddr, (size_t) ifp->iftype->hwalen);
  86.     rarp_output (ifp, hardware, hwaddr, qhwaddr);
  87.  
  88.     t = Arp_type[hardware].pendtime;
  89.     ++Rwaiting;
  90.     tprintf ("Trying...   %2d", t);
  91.     while (t--) {
  92.         kalarm (1000L);
  93.         if (kwait (&Rwaiting) != EALARM) {
  94.             kalarm (0);
  95.             --Rwaiting;
  96.             return 0;
  97.         }
  98.         tprintf ("\b\b%2d", t);
  99.     }
  100.     tputs ("\b\bTimeout.\n");
  101.     --Rwaiting;
  102.     return 0;
  103. }
  104.  
  105.  
  106. /* Handle incoming RARP packets according to RFC 903.
  107.  */
  108. void
  109. rarp_input (iface, bp)
  110. struct iface *iface;
  111. struct mbuf *bp;
  112. {
  113. struct arp rarp;
  114. struct arp_type *at;
  115. char shwaddr[MAXHWALEN];
  116.  
  117.     Rarp_stat.recv++;
  118.     if (ntoharp (&rarp, &bp) == -1)    /* Convert into host format */
  119.         return;
  120.     if (rarp.hardware >= NHWTYPES) {
  121.         /* Unknown hardware type, ignore */
  122.         Rarp_stat.badtype++;
  123.         return;
  124.     }
  125.     at = &Arp_type[rarp.hardware];
  126.     if (rarp.protocol != at->iptype) {
  127.         /* Unsupported protocol type, ignore */
  128.         Rarp_stat.badtype++;
  129.         return;
  130.     }
  131.     if ((int16) uchar (rarp.hwalen) > MAXHWALEN || uchar (rarp.pralen) != sizeof (int32)) {
  132.         /* Incorrect protocol addr length (different hw addr lengths
  133.          * are OK since AX.25 addresses can be of variable length)
  134.          */
  135.         Rarp_stat.badlen++;
  136.         return;
  137.     }
  138.     if (memcmp (rarp.shwaddr, at->bdcst, (size_t) at->hwalen) == 0) {
  139.         /* This guy is trying to say he's got the broadcast address! */
  140.         Rarp_stat.badaddr++;
  141.         return;
  142.     }
  143.     if (rarp.opcode == REVARP_REQUEST) {
  144.         /* We are not a server, so we can only answer requests for a
  145.          * hardware address that is our own. But would be possible to
  146.          * use the ARP table to answer requests for someone elses
  147.          * IP address.
  148.          */
  149.         if (memcmp (rarp.thwaddr, iface->hwaddr, (size_t) at->hwalen) == 0) {
  150.             memcpy (shwaddr, rarp.shwaddr, (size_t) at->hwalen);
  151.             /* Mark the end of the sender's AX.25 address
  152.              * in case he didn't
  153.              */
  154.             if (rarp.hardware == ARP_AX25)
  155.                 rarp.thwaddr[uchar (rarp.hwalen) - 1] |= E;
  156.             memcpy (rarp.shwaddr, iface->hwaddr, (size_t) at->hwalen);
  157.             rarp.sprotaddr = iface->addr;
  158.             rarp.tprotaddr = iface->addr;
  159.             rarp.opcode = REVARP_REPLY;
  160.  
  161.             if ((bp = htonarp (&rarp)) == NULLBUF)
  162.                 return;
  163.  
  164.             if (iface->forw != NULLIF)
  165.                 (void) (*iface->forw->output) (iface->forw, shwaddr, iface->forw->hwaddr, at->rarptype, bp);
  166.             else
  167.                 (void) (*iface->output) (iface, shwaddr, iface->hwaddr, at->rarptype, bp);
  168.             Rarp_stat.inreq++;
  169.         }
  170.     } else {
  171.         Rarp_stat.replies++;
  172.         if (Rwaiting) {
  173.             ksignal (&Rwaiting, 1);
  174.             tprintf ("\nRARP Reply: %s %s\n",
  175.                  (*at->format) (shwaddr, rarp.thwaddr),
  176.                  inet_ntoa (rarp.tprotaddr));
  177.         }
  178.     }
  179. }
  180.  
  181.  
  182. /* Send a RARP request to target to resolve hardware address hwaddr */
  183. static void
  184. rarp_output (struct iface *iface, int16 hardware, char *hwaddr, char *target)
  185. {
  186. struct arp rarp;
  187. struct mbuf *bp;
  188. struct arp_type *at;
  189.  
  190.     at = &Arp_type[hardware];
  191.     if (iface->output == NULLFP ((struct iface *, const char *, char *, int16, struct mbuf *)))    /*lint !e58 */
  192.         return;
  193.  
  194.     rarp.hardware = hardware;
  195.     rarp.protocol = at->iptype;
  196.     rarp.hwalen = (char) at->hwalen;
  197.     rarp.pralen = sizeof (int32);
  198.     rarp.opcode = REVARP_REQUEST;
  199.     memcpy (rarp.shwaddr, iface->hwaddr, (size_t) at->hwalen);
  200.     rarp.sprotaddr = 0;
  201.     memcpy (rarp.thwaddr, hwaddr, (size_t) at->hwalen);
  202.     rarp.tprotaddr = 0;
  203.     if ((bp = htonarp (&rarp)) == NULLBUF)
  204.         return;
  205.     (void) (*iface->output) (iface, target, iface->hwaddr, at->rarptype, bp);
  206.     Rarp_stat.outreq++;
  207. }
  208.  
  209.  
  210. static void
  211. rarpstat ()
  212. {
  213.     tprintf ("received %u badtype %u bogus addr %u reqst in %u replies %u reqst out %u\n",
  214.          Rarp_stat.recv, Rarp_stat.badtype, Rarp_stat.badaddr, Rarp_stat.inreq,
  215.          Rarp_stat.replies, Rarp_stat.outreq);
  216. }
  217.